Nest JS 权限控制 rabc 0 的一种实现

Nest JS 权限控制 rabc 0 的一种实现

文章更多的是在于记录。有看不懂的评论

2.1 RBAC 0 https://juejin.cn/post/6844904109863075853#heading-3

最简单的用户、角色、权限模型。这里面又包含了2种:

  • 用户和角色是多对一关系,即:一个用户只充当一种角色,一种角色可以有多个用户担当。
  • 用户和角色是多对多关系,即:一个用户可同时充当多种角色,一种角色可以有多个用户担当。

jwt

依赖包

@nestjs/jwt passport-jwt

  1. 构建 jwt 策略

这是用来对 token 进行处理的。他会在 request

jwt.strategy.ts

1
2
3
4
5
6
7
8
import { Injectable } from '@nestjs/common';import { ConfigService } from '@nestjs/config';import { PassportStrategy } from '@nestjs/passport';import { ExtractJwt, Strategy } from 'passport-jwt';import { IJwtData } from 'src/types/user';@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(private configService: ConfigService) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), secretOrKey: configService.get('jwtSecret'), }); }
validate(data: IJwtData) {
return data; }
}
  1. 生成 auth 模块
1
nest g res auth

auth.module.ts

1
2
3
4
5
6
7
8
import { Module } from '@nestjs/common';import { AuthService } from './auth.service';import { AuthController } from './auth.controller';import { JwtModule } from '@nestjs/jwt';import { ConfigService } from '@nestjs/config';import { JwtStrategy } from 'src/strategy/jwt.strategy';@Module({
imports: [
JwtModule.registerAsync({
inject: [ConfigService], useFactory: (configService: ConfigService) => {
return {
secret: configService.get('jwtSecret'), signOptions: {
expiresIn: '4h', }, }; }, }), ], controllers: [AuthController], providers: [AuthService, JwtStrategy], exports: [AuthService],})
export class AuthModule {}

auth.service.ts

1
2
3
4
5
6
7
8
9
10
import { InjectRedis } from '@liaoliaots/nestjs-redis';import { Injectable, UnauthorizedException } from '@nestjs/common';import { JwtService } from '@nestjs/jwt';import Redis from 'ioredis';import { IJwtData } from 'src/types/user';@Injectable()
export class AuthService {
constructor(
@InjectRedis()
private readonly redis: Redis, private jwtService: JwtService, ) {}
createToken(data: IJwtData) {
const token = this.jwtService.sign(data); this.redis.hset('dialogua:token', token, 1); return token; }
async validate(token?: string) {
if (!token) throw new UnauthorizedException(); const exit = await this.redis.hexists('dialogua:token', token); if (!exit) throw new UnauthorizedException(); }
}

全局守卫

auth.guard.ts

1
2
3
4
5
6
7
8
import { InjectRedis } from '@liaoliaots/nestjs-redis';import { ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common';import Redis from 'ioredis';import { AuthGuard } from '@nestjs/passport';import { ExtractJwt } from 'passport-jwt';import { Reflector } from '@nestjs/core';import { AuthService } from 'src/modules/auth/auth.service';@Injectable()
export class RbacAuthGuard extends AuthGuard('jwt') {
constructor(
@InjectRedis() private readonly redis: Redis, private authService: AuthService, private reflector: Reflector, ) {
super(); }
async canActivate(context: ExecutionContext): Promise<any> {
const isPublic = this.reflector.get<boolean>('isPublic', context.getHandler()); if (isPublic) return true; const request = context.switchToHttp().getRequest(); const token = ExtractJwt.fromAuthHeaderAsBearerToken()(request); await this.authService.validate(token); return super.canActivate(context); }
}

挂载

app.module.ts

在这个文件里挂载是因为 guard 有依赖。 如果用 globalGuard.
无法自动注入依赖

1
2
3
4
5
6
import { RedisModule } from '@liaoliaots/nestjs-redis';import { Module } from '@nestjs/common';import { ConfigModule, ConfigService } from '@nestjs/config';import { APP_GUARD } from '@nestjs/core';import { JwtService } from '@nestjs/jwt';import { TypeOrmModule } from '@nestjs/typeorm';import { AppController } from './app.controller';import { AppService } from './app.service';import config from './config';import { RbacAuthGuard } from './guards/auth.guard';import modules from './modules';@Module({
imports: [
...modules, ], controllers: [AppController], providers: [
// 这里。 {
provide: APP_GUARD, useClass: RbacAuthGuard, }, ],})
export class AppModule {}